// Timer.cpp
#include "include/Timer.h"
#include <stdexcept>
#include <thread>
#include <chrono>
#include <algorithm>

namespace Tool
{

struct Timer::TimerPrivater
{
    TimerPrivater(size_t slot_count, uint64_t slot_interval_ms)
        : m_slot_count(slot_count),
        m_slot_interval_ms(slot_interval_ms),
        m_current_slot(0),
        m_is_running(false),
        m_next_task_id(1),
        m_start_time(std::chrono::high_resolution_clock::now())
    {
        m_slots.resize(slot_count);
    }

    ~TimerPrivater()
    {
        StopAllTasks();
    }

    void Start()
    {
        if (m_is_running)
        {
            return;
        }

        m_is_running = true;
        m_thread = std::thread(&TimerPrivater::RunTimeWheel, this);
    }

    void StopAllTasks()
    {
        if (!m_is_running)
        {
            return;
        }

        m_is_running = false;
        if (m_thread.joinable())
        {
            m_thread.join();
        }

        std::lock_guard<std::mutex> lock(m_mutex);
        for (auto& slot : m_slots)
        {
            slot.clear();
        }
        m_task_map.clear();
    }

    uint64_t AddTask(uint64_t delay_ms, TimerTask::Callback callback, bool is_one_shot)
    {
        if (delay_ms == 0 || !callback)
        {
            return 0;
        }

        std::lock_guard<std::mutex> lock(m_mutex);
        uint64_t task_id = m_next_task_id++;

        // 计算任务所在的槽位和轮次
        uint64_t total_slots = delay_ms / m_slot_interval_ms;
        uint64_t rounds = total_slots / m_slot_count;
        size_t slot = (m_current_slot + total_slots % m_slot_count) % m_slot_count;

        // 创建任务并添加到槽和映射表
        auto task = std::make_shared<TimerTask>(delay_ms, std::move(callback), is_one_shot);
        task->remaining_rounds = rounds;
        m_slots[slot].push_back(task);
        m_task_map[task_id] = {slot, task};

        return task_id;
    }

    bool RemoveTask(uint64_t task_id)
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        auto it = m_task_map.find(task_id);
        if (it == m_task_map.end())
        {
            return false;
        }

        auto& [slot, task] = it->second;
        auto& task_list = m_slots[slot];
        task_list.erase(std::remove(task_list.begin(), task_list.end(), task), task_list.end());
        m_task_map.erase(it);
        return true;
    }

    void RunTimeWheel()
    {
        while (m_is_running)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(m_slot_interval_ms));

            std::lock_guard<std::mutex> lock(m_mutex);
            auto& current_tasks = m_slots[m_current_slot];
            std::list<std::shared_ptr<TimerTask>> repeat_tasks;

            for (auto& task : current_tasks)
            {
                if (task->remaining_rounds > 0)
                {
                    // 还需要多轮，减少轮次后放回当前槽
                    task->remaining_rounds--;
                    repeat_tasks.push_back(task);
                    continue;
                }

                try
                {
                    if (task->callback)
                    {
                        task->callback();
                    }
                }
                catch (const std::exception& e)
                {
                    std::cerr << "Timer task error: " << e.what() << std::endl;
                }

                // 周期性任务需要重新计算槽位并添加回去
                if (!task->is_one_shot)
                {
                    uint64_t total_slots = task->delay_ms / m_slot_interval_ms;
                    uint64_t rounds = total_slots / m_slot_count;
                    size_t slot = (m_current_slot + total_slots % m_slot_count) % m_slot_count;

                    task->remaining_rounds = rounds;
                    m_slots[slot].push_back(task);

                    // 更新任务映射中的槽位
                    for (auto& [id, entry] : m_task_map)
                    {
                        if (entry.second == task)
                        {
                            entry.first = slot;
                            break;
                        }
                    }
                }
                else
                {
                    for (auto it = m_task_map.begin(); it != m_task_map.end();)
                    {
                        if (it->second.second == task)
                        {
                            it = m_task_map.erase(it);
                        }
                        else
                        {
                            ++it;
                        }
                    }
                }
            }

            current_tasks.clear();
            current_tasks.splice(current_tasks.end(), repeat_tasks);

            // 移动到下一个槽
            m_current_slot = (m_current_slot + 1) % m_slot_count;
        }
    }

    size_t m_slot_count;                  // 时间槽数量
    uint64_t m_slot_interval_ms;         // 每个槽的时间间隔(毫秒)
    size_t m_current_slot;               // 当前槽位置
    std::vector<std::list<std::shared_ptr<TimerTask>>> m_slots;  // 时间槽数组

    using TaskMapEntry = std::pair<size_t, std::shared_ptr<TimerTask>>;
    std::unordered_map<uint64_t, TaskMapEntry> m_task_map;  // 任务ID到任务的映射

    std::thread m_thread;                // 时间轮线程
    std::atomic<bool> m_is_running;      // 运行状态标志
    std::mutex m_mutex;                  // 线程安全锁
    uint64_t m_next_task_id;             // 下一个任务ID

    // 基础计时相关
    std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
};

// 公开接口实现
Timer::Timer(size_t slot_count, uint64_t slot_interval_ms)
    : m_privater(std::make_unique<TimerPrivater>(slot_count, slot_interval_ms))
{
    m_privater->Start();
}

Timer::~Timer() = default;

void Timer::Reset()
{
    m_privater->m_start_time = std::chrono::high_resolution_clock::now();
}

double Timer::Elapsed() const
{
    auto now = std::chrono::high_resolution_clock::now();
    return std::chrono::duration_cast<std::chrono::milliseconds>(now - m_privater->m_start_time).count();
}

double Timer::ElapsedNanoseconds() const
{
    auto now = std::chrono::high_resolution_clock::now();
    return std::chrono::duration_cast<std::chrono::nanoseconds>(now - m_privater->m_start_time).count();
}

void Timer::SleepMs(int64_t ms)
{
    if (ms > 0)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(ms));
    }
}

void Timer::SleepUs(int64_t us)
{
    if (us > 0)
    {
        std::this_thread::sleep_for(std::chrono::microseconds(us));
    }
}

uint64_t Timer::AddTask(uint64_t delay_ms, TimerTask::Callback callback, bool is_one_shot)
{
    return m_privater->AddTask(delay_ms, std::move(callback), is_one_shot);
}

bool Timer::RemoveTask(uint64_t task_id)
{
    return m_privater->RemoveTask(task_id);
}

void Timer::StopAllTasks()
{
    m_privater->StopAllTasks();
}

bool Timer::IsRunning() const
{
    return m_privater->m_is_running;
}

} // namespace Tool
